package com.ywu.bpmn.flow.service;

import com.ywu.boot.context.YwuContext;
import com.ywu.boot.context.YwuContextHolder;
import com.ywu.bpmn.flow.build.entity.YwuNodeCommonEntity;
import com.ywu.bpmn.flow.build.entity.YwuNodeTableData;
import com.ywu.bpmn.flow.data.YwuFlowDefinitionRepository;
import com.ywu.bpmn.flow.data.YwuFlowInstanceRepository;
import com.ywu.bpmn.flow.dto.YwuFlowInstanceCommonDto;
import com.ywu.bpmn.flow.dto.YwuFlowInstanceCompleteDto;
import com.ywu.bpmn.flow.dto.YwuFlowInstanceConditionDto;
import com.ywu.bpmn.flow.entity.YwuFlowDefinitionEntity;
import com.ywu.bpmn.flow.entity.YwuFlowInstanceEntity;
import com.ywu.bpmn.flow.entity.YwuFlowTaskEntity;
import com.ywu.bpmn.flow.vo.QueryFlowInstanceListVo;
import com.ywu.bpmn.form.service.data.YwuFormDefinitionRepository;
import com.ywu.bpmn.form.service.dto.YwuFormInstanceDto;
import com.ywu.bpmn.form.service.dto.YwuFormInstanceJsonDto;
import com.ywu.bpmn.form.service.entity.YwuFormDefinitionEntity;
import com.ywu.bpmn.form.service.service.YwuFormInstanceService;
import com.ywu.bpmn.spi.dto.YwuBpmnDto;
import com.ywu.bpmn.spi.spi.YwuActivitiSpi;
import com.ywu.bpmn.spi.vo.YwuBpmnVariableVo;
import com.ywu.common.entity.PageList;
import com.ywu.common.gson.GsonUtils;
import com.ywu.common.page.PageService;
import com.ywu.common.result.CommonResult;
import com.ywu.common.utils.TimerIdGenerateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName YwuFlowInstanceService
 * @Description TODO
 * @Author GroundDemo
 * @Date 2025/4/23 15:45
 * @Version 1.0
 **/
@Service
@Slf4j
public class YwuFlowInstanceService {
    @Autowired
    private YwuFlowInstanceRepository repository;

    @Autowired
    private YwuFlowDefinitionRepository definitionRepository;

    @Autowired
    private YwuFormInstanceService formInstanceService;

    @Autowired
    private YwuFormDefinitionRepository formDefinitionRepository;

    @Autowired
    private YwuActivitiSpi spi;

    /**
    * @Author GroundDemo
    * @Description 查询代办的流程列表
    * @Date 15:46 2025/4/23
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> flowTodoList(YwuFlowInstanceCommonDto dto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        dto.setUserAccount(currentContext.getYwuContextUser().getUserAccount());
        dto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        List<YwuFlowInstanceCommonDto> resList = repository.queryFlowTodoList(dto);
        return CommonResult.success(resList);
    }

    /**
    * @Author GroundDemo
    * @Description 流程实例代办列表
    * @Date 16:01 2025/4/23
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> instanceTodoList(YwuFlowInstanceCommonDto dto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        dto.setUserAccount(currentContext.getYwuContextUser().getUserAccount());
        dto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        List<YwuFlowInstanceCommonDto> resList = repository.queryInstanceTodoList(dto);
        return CommonResult.success(resList);
    }

    /**
    * @Author GroundDemo
    * @Description 发起流程
    * @Date 18:05 2025/4/23
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    @Transactional
    public CommonResult<Object> startInstance(YwuFlowInstanceCommonDto dto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        // 判断当前是否存在该流程
        YwuFlowDefinitionEntity search = new YwuFlowDefinitionEntity();
        search.setId(dto.getFlowId());
        search.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        YwuFlowDefinitionEntity entity = definitionRepository.getEntity(search);
        if (Objects.isNull(entity)) {
            return CommonResult.error().setErrorCode("flow.is.not.exist");
        }
        // 判读当前是否已经发布
        if (entity.getStatus().equals(YwuFlowDefinitionEntity.DRAFT_STATUS)) {
            return CommonResult.error().setErrorCode("can.not.start.draft.flow");
        }
        // 创建表单实例
        YwuFormInstanceDto ywuFormInstanceDto = new YwuFormInstanceDto();
        ywuFormInstanceDto.setFormId(entity.getFormId());
        ywuFormInstanceDto.setFormInstanceJson(dto.getFormInstanceJson());
        ywuFormInstanceDto.setFormVersion(String.valueOf(entity.getCurrentVersion()));
        CommonResult<Object> result = formInstanceService.addFormInstance(ywuFormInstanceDto);
        if (Objects.isNull(result) || !"200".equals(result.getCode())) {
            return CommonResult.error().setErrorCode("form.instance.create.error");
        }
        // 构建流程实例对象，实例状态为STARTING
        YwuFlowInstanceEntity insert = new YwuFlowInstanceEntity();
        insert.setId(TimerIdGenerateUtil.nextId());
        insert.setFlowId(entity.getId());
        insert.setFlowVersion(String.valueOf(entity.getCurrentVersion()));
        insert.setFormInstanceId((String) result.getData());
        insert.setStatus(YwuFlowInstanceEntity.STARING_STATUS);
        insert.createInfo(currentContext.getYwuContextUser().getUserAccount());
        insert.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        insert.setCurrentNode("nid-start");
        repository.insert(insert);
        // 调用引擎的spi，发起流程
        YwuBpmnDto ywuBpmnDto = new YwuBpmnDto();
        ywuBpmnDto.setKey("flow_" + entity.getId());
        // 构建传入流程引擎的变量
        Map<String, Object> variable = new HashMap<>();
        // 流程发起人
        variable.put("START_BY", currentContext.getYwuContextUser().getUserAccount());
        // 流程实例ID
        variable.put("instanceId", insert.getId());
        // 流程变量
        String flowJson = entity.getFlowJson();
        YwuNodeCommonEntity flowNodeEntity = GsonUtils.deserialize(flowJson, YwuNodeCommonEntity.class);
        List<YwuNodeTableData> tableData = flowNodeEntity.getGlobalProperties().getTableData();
        String flowInstanceJson = dto.getFlowInstanceJson();
        List<YwuFormInstanceJsonDto> ywuFlowInstanceJsonDtoList = GsonUtils.deserializeList(flowInstanceJson, YwuFormInstanceJsonDto.class);
        if (!CollectionUtils.isEmpty(tableData)) {
            for (YwuNodeTableData nodeTableData : tableData) {
                Object resValue = nodeTableData.getParamValue();
                for (YwuFormInstanceJsonDto ywuFormInstanceJsonDto : ywuFlowInstanceJsonDtoList) {
                    if (nodeTableData.getParamName().equals(ywuFormInstanceJsonDto.getCode())) {
                        resValue = ywuFormInstanceJsonDto.getValue();
                        break;
                    }
                }
                variable.put("FLOW_" + nodeTableData.getParamName(), resValue);
            }
        }
        // 表单变量
        String formInstanceJson = dto.getFormInstanceJson();
        List<YwuFormInstanceJsonDto> ywuFormInstanceJsonDtoList = GsonUtils.deserializeList(formInstanceJson, YwuFormInstanceJsonDto.class);
        if (!CollectionUtils.isEmpty(ywuFormInstanceJsonDtoList)) {
            for (YwuFormInstanceJsonDto ywuFormInstanceJsonDto : ywuFormInstanceJsonDtoList) {
                variable.put("FORM_" + ywuFormInstanceJsonDto.getCode(), ywuFormInstanceJsonDto.getValue());
            }
        }
        ywuBpmnDto.setVariable(variable);
        spi.start(ywuBpmnDto);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 查询流程实例详情，包括表单构建Json、流程构建JSON，表单实例数据
    * @Date 22:59 2025/4/23
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryInstanceDetailInfo(YwuFlowInstanceCommonDto dto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        dto.setUserAccount(currentContext.getYwuContextUser().getUserAccount());
        dto.setStatus(YwuFlowTaskEntity.RUNNING_STATUS);
        dto.setTaskId(dto.getTaskId());
        dto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        YwuFlowInstanceCommonDto ywuFlowInstanceCommonDto = repository.queryInstanceDetailInfo(dto);
        return CommonResult.success(ywuFlowInstanceCommonDto);
    }

    /**
    * @Author GroundDemo
    * @Description 审批流程
    * @Date 10:53 2025/4/24
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    @Transactional
    public CommonResult<Object> completeInstance(YwuFlowInstanceCompleteDto dto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        // 判断当前任务ID是否为当前责任人
        YwuFlowTaskEntity ywuFlowTaskEntity = new YwuFlowTaskEntity();
        ywuFlowTaskEntity.setAssignee(currentContext.getYwuContextUser().getUserAccount());
        ywuFlowTaskEntity.setFlowInstanceId(dto.getId());
        ywuFlowTaskEntity.setTaskId(dto.getTaskId());
        YwuFlowTaskEntity queryRes = repository.getTaskInfoByInstanceIdAndAssignee(ywuFlowTaskEntity);
        // 如果查询结果为空，则表示当前用户无法审批，返回异常
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setErrorCode("current.node.user.can.not.complete");
        }
        // 获取表单实例信息, 并修改表单实例信息
        YwuFlowInstanceEntity searchInstance = new YwuFlowInstanceEntity();
        searchInstance.setId(dto.getId());
        YwuFlowInstanceCommonDto instanceById = repository.getInstanceAndFlowInfoByInstanceId(searchInstance);
        // 根据表单实例ID修改表单实例数据
        YwuFormInstanceDto ywuFormInstanceDto = new YwuFormInstanceDto();
        ywuFormInstanceDto.setId(instanceById.getFormInstanceId());
        ywuFormInstanceDto.setFormInstanceJson(dto.getFormInstanceJson());
        ywuFormInstanceDto.setFormId(instanceById.getFormId());
        CommonResult<Object> result = formInstanceService.updateFormInstance(ywuFormInstanceDto);
        if (Objects.isNull(result) || !"200".equals(result.getCode())) {
            return CommonResult.error().setErrorCode("form.instance.update.error");
        }
        // 更新task的result
        queryRes.setTaskResult(dto.getResult());
        queryRes.setTaskContent(dto.getResultMsg());
        repository.updateTaskResult(queryRes);
        // 调用引擎侧进行审批
        YwuBpmnDto ywuBpmnDto = new YwuBpmnDto();
        ywuBpmnDto.setTaskId(queryRes.getTaskId());
        // 构建变量
        Map<String, Object> variable = new HashMap<>();
        String formInstanceJson = dto.getFormInstanceJson();
        List<YwuFormInstanceJsonDto> ywuFormInstanceJsonDtoList = GsonUtils.deserializeList(formInstanceJson, YwuFormInstanceJsonDto.class);
        if (!CollectionUtils.isEmpty(ywuFormInstanceJsonDtoList)) {
            for (YwuFormInstanceJsonDto ywuFormInstanceJsonDto : ywuFormInstanceJsonDtoList) {
                variable.put("FORM_" + ywuFormInstanceJsonDto.getCode(), ywuFormInstanceJsonDto.getValue());
            }
        }
        // 设置审批结果
        variable.put("result", dto.getResult());
        log.debug("variable is {}", variable);
        ywuBpmnDto.setVariable(variable);
        spi.complete(ywuBpmnDto);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 查询审批历史流程列表
    * @Date 20:31 2025/4/24
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryCompleteHistoryFlowList(YwuFlowInstanceCommonDto dto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        dto.setUserAccount(currentContext.getYwuContextUser().getUserAccount());
        dto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        List<YwuFlowInstanceCommonDto> queryRes = repository.queryFlowHistoryList(dto);
        // 根据查询的结果进行分组，填充分组数量
        Map<String, List<YwuFlowInstanceCommonDto>> resMap = queryRes.stream().collect(Collectors.groupingBy(res -> res.getFlowId()));
        // 构建返回参数
        ArrayList<YwuFlowInstanceCommonDto> resList = new ArrayList<>();
        for (String key : resMap.keySet()) {
            YwuFlowInstanceCommonDto tempDto = new YwuFlowInstanceCommonDto();
            List<YwuFlowInstanceCommonDto> ywuFlowInstanceCommonDtoList = resMap.get(key);
            tempDto.setFlowId(ywuFlowInstanceCommonDtoList.get(0).getFlowId());
            tempDto.setId(ywuFlowInstanceCommonDtoList.get(0).getId());
            tempDto.setFlowNameCn(ywuFlowInstanceCommonDtoList.get(0).getFlowNameCn());
            tempDto.setFlowNameEn(ywuFlowInstanceCommonDtoList.get(0).getFlowNameEn());
            tempDto.setInstanceCount(ywuFlowInstanceCommonDtoList.size());
            resList.add(tempDto);
        }
        return CommonResult.success(resList);
    }

    /**
    * @Author GroundDemo
    * @Description 查询历史流程审批流程实例列表
    * @Date 10:20 2025/4/25
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryCompleteHistoryInstanceList(YwuFlowInstanceCommonDto dto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        dto.setUserAccount(currentContext.getYwuContextUser().getUserAccount());
        dto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        List<YwuFlowInstanceCommonDto> resList = repository.queryInstanceHistoryList(dto);
        return CommonResult.success(resList);
    }

    /**
    * @Author GroundDemo
    * @Description 查询历史实例详情
    * @Date 10:58 2025/4/25
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryHistoryInstanceDetail(YwuFlowInstanceCommonDto dto) {
        dto.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        YwuFlowInstanceCommonDto ywuFlowInstanceCommonDto = repository.queryHistoryInstanceDetailInfo(dto);
        return CommonResult.success(ywuFlowInstanceCommonDto);
    }

    /**
    * @Author GroundDemo
    * @Description 查询流程实例列表
    * @Date 11:01 2025/4/25
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryFlowInstanceList(YwuFlowInstanceConditionDto dto) {
        // 构建分页参数
        PageService.execPageStartAndEnd(dto.getPageInfo());
        // 根据ID查询流程定义
        YwuFlowDefinitionEntity search = new YwuFlowDefinitionEntity();
        search.setId(dto.getFlowId());
        search.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        YwuFlowDefinitionEntity queryRes = definitionRepository.getEntity(search);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setErrorCode("flow.definition.not.exist");
        }
        // 根据版本和流程ID查询流程实例列表
        int count = repository.queryFlowInstanceCount(dto);
        // 查询列表
        List<QueryFlowInstanceListVo> queryFlowInstanceListVos = repository.queryFlowInstancePage(dto);
        PageList<QueryFlowInstanceListVo> resPage = new PageList<>(dto.getPageInfo().getPageIndex(), dto.getPageInfo().getPageSize(), count, queryFlowInstanceListVos);
        return CommonResult.success(resPage);
    }

    /**
    * @Author GroundDemo
    * @Description 查询流程实例列表
    * @Date 11:01 2025/4/25
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryInstanceList(YwuFlowInstanceConditionDto dto) {
        // 构建分页参数
        PageService.execPageStartAndEnd(dto.getPageInfo());
        dto.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        // 查询数量
        int count = repository.queryInstanceCount(dto);
        // 查询列表
        List<YwuFlowInstanceEntity> queryRes = repository.queryInstancePage(dto);
        PageList<YwuFlowInstanceEntity> resPage = new PageList<>(dto.getPageInfo().getPageIndex(), dto.getPageInfo().getPageSize(), count, queryRes);
        return CommonResult.success(resPage);
    }

    /**
    * @Author GroundDemo
    * @Description 查询流程实例所有变量
    * @Date 11:01 2025/4/25
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryAllVariableByInstanceId(YwuFlowInstanceConditionDto dto) {
        YwuFlowInstanceEntity ywuFlowInstanceEntity = new YwuFlowInstanceEntity();
        ywuFlowInstanceEntity.setId(dto.getId());
        ywuFlowInstanceEntity.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        YwuFlowInstanceEntity queryRes = repository.getEntity(ywuFlowInstanceEntity);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setErrorCode("flow.instance.not.exist");
        }
        // 调用bpmn的spi查询变量信息
        YwuBpmnDto ywuBpmnDto = new YwuBpmnDto();
        ywuBpmnDto.setProcessInstanceId(queryRes.getBpmnInstanceId());
        CommonResult<Object> res = spi.queryAllVariables(ywuBpmnDto);
        if (!"200".equals(res.getCode())) {
            return res;
        }
        Object data = res.getData();
        List<YwuBpmnVariableVo> ywuBpmnVariableVos = GsonUtils.deserializeList(GsonUtils.serialize(data), YwuBpmnVariableVo.class);
        return CommonResult.success(ywuBpmnVariableVos);
    }

    /**
    * @Author GroundDemo
    * @Description 查询任务列表
    * @Date 11:01 2025/4/25
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryTaskList(YwuFlowInstanceConditionDto dto) {
        YwuFlowTaskEntity ywuFlowTask = new YwuFlowTaskEntity();
        ywuFlowTask.setFlowInstanceId(dto.getId());
        ywuFlowTask.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        List<YwuFlowTaskEntity> taskList = repository.getTaskList(ywuFlowTask);
        return CommonResult.success(taskList);
    }
}
